﻿using BaseUtils.Helper;
using BaseUtils.Utils;
using Service.src.Model.Folw;
using Service.src.NW.Enum;
using Service.src.NW.Model.Folw;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Service.src.NW.Processor.Core
{
    public class CalculatorProcessor : BaseProcessor
    {
        internal static void Run(NodeProcessor nodeProcessor, NodeInputParam nodeInputParam)
        {
            ConcurrentDictionary<string, object> keyValuePairs = new ConcurrentDictionary<string, object>();
            nodeProcessor.NodeStatus = Model.Enum.NodeStatusEnum.SUCCESS;
            if (nodeInputParam?.NodeLogic?.Calculator?.InputParams.Any()!=true)
            {
                nodeProcessor.NodeStatus = Model.Enum.NodeStatusEnum.ERROR;
                return;
            }
            foreach (NodeDataSource nds in nodeInputParam?.NodeLogic?.Calculator?.InputParams)
            {
                try
                {
                    keyValuePairs.Clear();
                    List<NodeDataSource> InputParamNodeDataSource = ParseParam(nds.ParamName);
                    switch (nds.ValueType)
                    {
                        case "int":
                        case "long":
                        case "float":
                        case "bool":
                            foreach (NodeDataSource item in InputParamNodeDataSource)
                            {
                                NodeDataSource NDS = GetNodeInputParam(nodeProcessor, item);
                                keyValuePairs.TryAdd(item.DataSource + "_" + item.DataSourceId + "_" + item.ParamName, float.Parse(NDS.Value+""));
                            }
                            dynamic CalculationResults = CalculatorHelper.Computing(keyValuePairs, nds.ParamName);
                            SetNodeOutParamValue(nodeProcessor, nds.TargetParamName, CalculationResults);
                            break;
                        default:
                            foreach (NodeDataSource item in InputParamNodeDataSource)
                            {
                                string _key = "${" + item.DataSource + "_" + item.DataSourceId + "_" + item.ParamName + "}";
                                NodeDataSource Get = GetNodeInputParam(nodeProcessor, item);
                                nds.ParamName = nds.ParamName.Replace(_key, Get.Value + "");
                            }
                            SetNodeOutParamValue(nodeProcessor, nds.TargetParamName, nds.ParamName);
                            break;
                    }
                }
                catch (Exception ex)
                {
                    nodeProcessor.NodeStatus = Model.Enum.NodeStatusEnum.ERROR;
                    SendNodeLoggerError(nodeProcessor, $"计算失败，节点id={nodeProcessor.id}，公式：{nds.ParamName}，原因：{ex.Message}，可能变量中存在字符串等非数字的值，请检查", ex);
                }
            }
        }

        static List<NodeDataSource> ParseParam(string formula)
        {
            List<NodeDataSource> placeholders = new List<NodeDataSource>();
            MatchCollection matches = Regex.Matches(formula, @"\$\{([^}]+)\}");
            foreach (Match match in matches)
            {
                string _res = match.Groups[1].Value;
                NodeDataSource source = new NodeDataSource();
                List<string> Separator = ExtractPartsWithNumberSeparator(_res);
                source.DataSource = ConvertHelper.ToEnum<DeviceTypeEnum>(Separator[0]);
                source.DataSourceId = int.Parse(Separator[1]);
                source.ParamName = Separator[2];
                placeholders.Add(source);
            }
            return placeholders;
        }

        /// <summary>
        /// 提取字符串中数字分隔符前后的非数字字符
        /// </summary>
        /// <param name="input">输入字符串</param>
        /// <returns>数字分隔后的非数字部分列表</returns>
        public static List<string> ExtractPartsWithNumberSeparator(string input)
        {
            List<string> result = new List<string>();

            if (string.IsNullOrEmpty(input))
                return result;

            // 正则表达式匹配：非数字部分或数字部分
            // (\D+) 匹配1个或多个非数字字符
            // (\d+) 匹配1个或多个数字
            var matches = Regex.Matches(input, @"(\D+)|(\d+)");

            foreach (Match match in matches)
            {
                string part = match.Value;

                // 处理非数字部分的下划线
                if (!char.IsDigit(part[0]))
                {
                    // 去除首尾下划线，合并连续下划线
                    part = Regex.Replace(part.Trim('_'), @"_+", "_");

                    // 跳过空字符串（可能全是下划线的情况）
                    if (string.IsNullOrEmpty(part))
                        continue;
                }

                result.Add(part);
            }

            return result;
        }

    }
}
